home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tar316.zip / RESTORE.C < prev    next >
Text File  |  1994-07-02  |  17KB  |  609 lines

  1. /* restore.c - extract regular files from (tape) archive.
  2.  * This is a part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date: 11 Mar 1993
  5.  */
  6. #include <stdio.h>
  7. #include <errno.h>
  8.  
  9. #include "sysup.h"
  10. #include "modern.h"
  11. #ifdef MODERN
  12. #    include <string.h>
  13. #else
  14.     char *strncpy();
  15.     int  strlen();
  16. #endif
  17.  
  18. #ifdef MSDOS
  19. #    include <io.h>
  20. #    include <dos.h>
  21. #    include <stdlib.h>
  22. #    ifdef __TURBOC__
  23. #        include <dir.h>
  24. #    else
  25. #        include <direct.h>
  26. #    endif
  27. #else
  28.     int  access(), creat(), open(), close(), link(), unlink();
  29.     int  write(), chown(), utime();
  30.     char *malloc();
  31.         long lseek();
  32.     void free();
  33. #endif
  34.  
  35. #include "lzwbits.h"
  36. #include "lzwhead.h"
  37. #include "compress.h"
  38. #include "zippipe.h"
  39. #include "crc32.h"
  40. #include "define.h"
  41. #include "lzpack.h"
  42.  
  43. char ofname[MAXTNAME
  44. #ifdef MSDOS
  45.             +MAXFILE
  46. #endif
  47.             +1];
  48.  
  49. void extwrerr()
  50. {
  51.    (void)fprintf(myout, "Tar: error extracting \'%s\'\n", ofname);
  52.    done(EWRITE);
  53. }
  54.  
  55. #ifdef MSDOS
  56. static void setime __ARGS__(( int, long ));
  57.  
  58. static void setime(h, mt)
  59. int h; long mt;
  60. {
  61.    struct date d;
  62.    struct time t;
  63.    struct ftime f;
  64.  
  65.    if (m_flag) return;
  66.    unixtodos(mt, &d, &t);
  67.    f.ft_tsec  = t.ti_sec;
  68.    f.ft_min   = t.ti_min;
  69.    f.ft_hour  = t.ti_hour;
  70.    f.ft_day   = d.da_day;
  71.    f.ft_month = d.da_mon;
  72.    f.ft_year  = d.da_year - 1980;
  73.    (void)setftime(h, &f);
  74. }
  75.  
  76. #define wcnt_type unsigned short
  77. #define MAXWARN  8
  78.  
  79. static renamed = FALSE;
  80. static wcnt_type wcount = 0;
  81. static nwarn = 0;
  82.  
  83. static struct { wcnt_type lru; char wnm[MAXTNAME]; } wlist[MAXWARN];
  84.  
  85. static void wrename __ARGS__(( char * ));
  86.  
  87. static void wrename(n)
  88. char *n;
  89. {
  90.    register i;
  91.  
  92.    renamed = FALSE;
  93.    for (i=0; i<nwarn; i++) {
  94.      if (strncmp(wlist[i].wnm, n, MAXTNAME) == 0) {
  95.         wlist[i].lru = wcount++; return;
  96.      }
  97.    }
  98.    (void)printf("Tar: warning: renamed to \'%s\'\n", n);
  99.    if (nwarn < MAXWARN) {
  100.       i = nwarn++;
  101.    } else {
  102.       register j;
  103.       /* Find the least recently used entry */
  104.       for (i=0, j=1; j<MAXWARN; j++) {
  105.          if (wlist[j].lru < wlist[i].lru) i = j;
  106.       }
  107.    }
  108.    (void)strncpy(wlist[i].wnm, n, MAXTNAME);
  109.    wlist[i].lru = wcount++;
  110. }
  111.  
  112. #define CH_DOT '-'
  113. #define CH_BAD '$'
  114.  
  115. static void uname __ARGS__(( char * ));
  116.  
  117. static void uname(fname) /* convert UNIX file name to DOS */
  118. char fname[];
  119. {
  120.    static char invalid[] = "^+=/[]:;\',?*\\<>|\".";
  121.    register char *p = fname;
  122.    register i, offext/* offset to file name extension */;
  123.    register j, limcpy, tmpren;
  124.  
  125.    if (p[1] == ':' && (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
  126.       p += 2;
  127.  
  128.    tmpren = FALSE;
  129.    while (*p) {
  130.       if (*p == '/') {
  131.          ++p; /* Forget dir name changes */ tmpren = FALSE;
  132.       }
  133.  
  134.       for (offext=i=0; p[i] && p[i]!='/'; i++) {
  135.          if (p[i] == '.') {
  136.             if (i == 0) {
  137.                if (p[1]=='.' && (p[2]=='/' || p[2]=='\0')) {
  138.                   /* This is '..' directory, skip */ ++i;
  139.                } else if (p[1]!='/' && p[1]!='\0') {
  140.                   /* This is not current directory */
  141.                   p[0] = CH_DOT; tmpren = TRUE;
  142.                }
  143.             } else {
  144.                if (offext) {
  145.                   p[offext] = CH_DOT; tmpren = TRUE;
  146.                }
  147.                offext = i;
  148.             }
  149.          } else if (p[i]<=' ' || p[i]>'~' || strchr(invalid, p[i])) {
  150.             p[i] = CH_BAD; tmpren = TRUE;
  151.          }
  152.       }
  153.       if (!offext) offext = i;
  154.       limcpy = MAXTNAME - (int)(p-fname) - offext;
  155.       i -= offext;
  156.       if (offext <= 8) {
  157.          j = offext;
  158.       } else {
  159.          (void)strncpy(p+8, p+offext, i>4 ? 4 : limcpy);
  160.          tmpren = TRUE;
  161.          j = 8;
  162.       }
  163.       if (i <= 4) {
  164.          j += i;
  165.       } else {
  166.          (void)strncpy(p+(offext>8 ? 12 : offext+4), p+i+offext, limcpy-i);
  167.          tmpren = TRUE;
  168.          j += 4;
  169.       }
  170.       p += j;
  171.    }
  172.    if (tmpren) renamed = TRUE;
  173. }
  174. #else
  175. #    define setime(h,t)
  176. #    define uname(s)
  177. #endif
  178.  
  179. int makedir __ARGS__((char *, int));
  180. int testdir __ARGS__((char *));
  181.  
  182. /*ARGSUSED*/ int makedir(p, to_print)
  183. char *p; int to_print;
  184. {
  185. #ifdef UNIX
  186. #   ifdef RMKDIR
  187.          if (mkdir(p, 0777) != 0 && to_print) {
  188.             (void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
  189.             return ERROR;
  190.          }
  191. #   else
  192.          switch (bincall("mkdir", p)) {
  193.             case  0: break;
  194.             case -1: (void)fprintf(myout, "Tar: fault run mkdir!\n");
  195.             default: done(0);
  196.          }
  197. #   endif
  198.          if (!o_flag) (void)chown(p,(int)st.st_uid,(int)st.st_gid);
  199. #endif
  200. #ifdef MSDOS
  201.          if (mkdir(p) != 0 && to_print) {
  202.             (void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
  203.             return ERROR;
  204.          }
  205. #endif
  206.    return 0;
  207. }
  208.  
  209. int testdir(p)
  210. char *p;
  211. {
  212.    register j;
  213.    register k = FALSE;
  214. #ifndef UNIX
  215.    register char *q = p;
  216. #endif
  217. #ifdef MSDOS
  218.    renamed = FALSE;
  219. #endif
  220.    for (j=1; j<MAXTNAME && p[j]; j++) {/* check directories */
  221.       if (p[j] == '/') {
  222.          p[j] = 0;
  223. #ifndef UNIX
  224.          uname(q); q = p + j + 1;
  225. #endif
  226.          if (access(p, 1) < 0) {
  227.             if (makedir(p, TRUE) != 0) return ERROR;
  228.             k = TRUE;
  229.          }
  230.          p[j] = '/';
  231.       }
  232.    }
  233. #ifdef MSDOS
  234.    if (renamed && v_flag) wrename(p);
  235. #endif
  236.    return k;
  237. }
  238.  
  239. long thisread;
  240.  
  241. int arcget __ARGS__((void))
  242. {
  243.    if (v_flag && !(thisread & 07777)) percent(thisread, st.st_size);
  244.    return thisread<st.st_size ? (++thisread, readbyte()) : EOF;
  245. }
  246.  
  247. static int  o_file, indput;
  248. static long thiscsum;
  249.  
  250. static void dstput(c)
  251. int c;
  252. {
  253.    thiscsum += c; ((unsigned char *)pk_out)[indput++] = c;
  254.    if (indput >= pksize) {
  255.       if (write(o_file, pk_out, pksize) != pksize) {
  256.          if (v_flag) (void)fprintf(myout, "\n");
  257.          extwrerr();
  258.       }
  259.       indput = 0;
  260.    }
  261. }
  262.  
  263. #define savename(s) ((void)strncpy(ofname,(s),MAXTNAME),ofname[MAXTNAME]='\0')
  264.  
  265. static int newfile __ARGS__(( char *, int ));
  266.  
  267. static int newfile(name, mode)
  268. char *name; int mode;
  269. {
  270. #ifdef MSDOS
  271.    int h, caccess;
  272.    unsigned cmode;
  273.    register k = 0;
  274.  
  275.    savename(name);
  276.    caccess = o_flag ? O_CREAT+O_EXCL+O_WRONLY+O_BINARY :
  277.                       O_CREAT+O_TRUNC+O_WRONLY+O_BINARY;
  278.    cmode = (mode & 0444 ? S_IREAD  : 0) |
  279.            (mode & 0222 ? S_IWRITE : 0) |
  280.            (mode & 0111 ? S_IEXEC  : 0);
  281.    if ((h = open(name, caccess, cmode)) < 0) {
  282.       if (errno == ENOENT || errno == ENOPATH) {
  283.          if ((k=testdir(name)) == TRUE) h = open(name, caccess, cmode);
  284.       } else if (errno == EEXIST && o_flag) {
  285.          static char del[4] = "^~\'`";
  286.          register unsigned ntry = 0;
  287.          register nb, len, i, j;
  288.          char suffix[5];
  289.  
  290.          if ((len = strlen(name)) > MAXTNAME) goto end;
  291.          for (nb=len; nb>0 && name[nb-1]!='/' && name[nb-1]!=':'; nb--) {
  292.             if (name[nb] == '.') len = nb;
  293.          }
  294.          len -= nb;
  295.          do {
  296.             ++ntry;
  297.             /* Convert number of try into suffix */
  298.             suffix[0] = del[ntry & 3];
  299.             for (i=1, j=ntry>>2; j; j>>=5) {
  300.                suffix[i++] = ((j & 037) < 10 ? '0': 'A'-10) + (j & 037);
  301.             }
  302.             suffix[i] = '\0';
  303.             /* Replace end of the name by suffix */
  304.             if (len < 8) {
  305.                (void)strcat(
  306.                         strcpy(ofname+nb+(len+i<8 ? len : 8-i), suffix),
  307.                         name+nb+len);
  308.             } else {
  309.                (void)strncpy(ofname+nb+len-i, suffix, i);
  310.             }
  311.             renamed = TRUE;
  312.             h = open(ofname, caccess, cmode);
  313.          } while (h<0 && errno == EEXIST && ntry);
  314.       }
  315.    }
  316. end:
  317.    if (h < 0) {
  318.       if (k!=ERROR) (void)fprintf(myout,"Tar: can\'t create \'%s\'\n",name);
  319.    } else {
  320.       if (renamed && v_flag) wrename(ofname);
  321.       if ((mode & 0777) == 0) (void)_chmod(name, 1, FA_HIDDEN);
  322.    }
  323.    return h;
  324. #else
  325.    register j = 0;
  326.    register h;
  327.  
  328.    savename(name);
  329.    do {
  330.       if ((h = creat(name, (int)(mode & 07777))) >= 0) {
  331.          if (!o_flag) (void)chown(name, (int)st.st_uid, (int)st.st_gid);
  332.          return h;
  333.       }
  334.    } while (++j < 2 && testdir(name) == TRUE);
  335.  
  336.    if (j > 1) (void)fprintf(myout, "Tar: can\'t create \'%s\'\n", name);
  337.    return ERROR;
  338. #endif
  339. }
  340.  
  341. static void pfile __ARGS__((char *, long, long));
  342.  
  343. static void pfile(name, bytes, blocks)
  344. char name[]; long bytes, blocks;
  345. {
  346.    if (v_flag) {
  347.       (void)fprintf(myout, "x %s, %ld bytes, %ld tape blocks",
  348.                     name, bytes, blocks);
  349.       (void)fflush(myout);
  350.    }
  351. }
  352.  
  353. static int xany __ARGS__((void))
  354. {
  355.    (void)fprintf(stderr, " Extract anyway? ");
  356.    (void)fflush(stderr);
  357.    return YES_NO();
  358. }
  359.  
  360. int restore(p)
  361. register char *p;
  362. {
  363.    register j;
  364.  
  365.    register long bytes, blocks;
  366.    static char no_mem[] = "\nTar: no memory to unpack.";
  367.    static char e[] = "    \n";
  368.    short nx=0, allx; long l=0, xinfo;
  369.    int multy = FALSE; /* Multyvolume processing flag */
  370.    extern int soctul __ARGS__((char*, long*));
  371. #ifdef MSDOS
  372.    renamed = FALSE;
  373. #endif
  374.    if (hblock->m.filetype == GF_MUL) {
  375.       (void)soctul(hblock->x.offset, &xinfo);
  376.       multy = TRUE;
  377.    } else {
  378.       if ((nx = isextent(&allx, &xinfo)) > 0) multy = TRUE;
  379.    }
  380.    bytes  = codesize > st.st_size ? codesize : st.st_size;
  381.    blocks = (st.st_size + BLKSIZE-1)/BLKSIZE;
  382.    if (pktype == PKfLZW && !multy && st.st_size >= codesize) {
  383.       j = strlen(p);
  384.       if (p[--j] != 'Z' || p[--j] != '.') goto regular;
  385.       p[j] = '\0';
  386.       uname(p);
  387.       if ((o_file = newfile(p, st.st_mode)) < 0) {
  388.          skipfile(); return ERROR;
  389.       }
  390.       pfile(p, bytes, blocks);
  391.       p[j] = '.';
  392.       (void)z_getmem(BITS);
  393.       thisread = 0; indput = 0; thiscsum = 0;
  394.       if ((j = dbegin(arcget)) == 0) {
  395.          do {
  396.             j = dpiece(pk_out, pksize);
  397.             if (j > 0) {
  398.                if (write(o_file, pk_out, j) != j) {
  399.                   if (v_flag) (void)fprintf(myout, "\n");
  400.                   extwrerr();
  401.                }
  402.                if (v_flag) percent(thisread, st.st_size);
  403.             }
  404.          } while (j == pksize);
  405.          (void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
  406.          goto xend;
  407.       } else if (j > 0) {
  408.          if (v_flag) (void)fprintf(myout, " is not in compressed format\n");
  409.       } else {
  410.          if (!xany()) done(ESMALL);
  411.       }
  412.       bacouple(); z_relmem();
  413.    }
  414. regular:
  415.    uname(p);
  416.    if (nx > 1 || (hblock->m.filetype == GF_MUL && xinfo > 0)) {
  417.       /* Multivolume processing */
  418.       if ((o_file = open(p, O_WRONLY|O_BINARY)) >= 0) {
  419.          savename(p);
  420.          if ((l=lseek(o_file, 0L, 2)) == -1L) {
  421.             (void)fprintf(myout, " Tar: \'%s\' seek error\n", p);
  422.             goto fault;
  423.          }
  424.          if (hblock->m.filetype == GF_MUL && l != xinfo) {
  425.             if (w_flag) {
  426.                (void)fprintf(stderr,
  427.                   " Tar: \'%s\' mismatch size. Append? ", p);
  428.                (void)fflush(stderr);
  429.                if (YES_NO()) goto opened;
  430.             } else {
  431.                (void)fprintf(myout,
  432.                   " Tar: warning: \'%s\' mismatch size\n", p);
  433.             }
  434.             l = lseek(o_file, xinfo, 0);
  435.          }
  436.          goto opened;
  437.       } else if (errno == ENOENT) {
  438.          if (w_flag) {
  439.             (void)fprintf(stderr,
  440.                " Tar: \'%s\' does not exist.", p);
  441.             if (!xany()) goto fault;
  442.          } else {
  443.             (void)fprintf(myout,
  444.                " Tar: warning: \'%s\' does not exist\n", p);
  445.             goto fault;
  446.          }
  447.       } else {
  448.          (void)fprintf(myout, "Tar: can\'t append \'%s\'\n", p);
  449.          goto fault;
  450.       }
  451.    }
  452.    if ((o_file = newfile(p, st.st_mode)) < 0) goto fault;
  453. opened:
  454.    pfile(ofname, bytes, blocks);
  455.  
  456.    if (st.st_size >= codesize || multy) {/* file was not packed */
  457.       if (v_flag) {
  458.          if (nx > 0) {
  459.             (void)fprintf(myout," [extent #%d of %d]", nx, allx);
  460.          } else if (hblock->m.filetype == GF_MUL) {
  461.             (void)fprintf(myout," [");
  462.             if (l != xinfo)
  463.                (void)fprintf(myout,"from %ld - ", xinfo);
  464.             (void)fprintf(myout,"append @%ld]", l);
  465.          }
  466.          (void)fprintf(myout, "\n");
  467.       }
  468.       (void)readarch(o_file, st.st_size);
  469.       if (nx > 1 && nx == allx && lseek(o_file, 0L, 2) != xinfo) {
  470.          /* last extent extracted, so check for total file size */
  471.          (void)fprintf(myout,"Tar: warning: \'%s\' changed size\n",ofname);
  472.       }
  473.    } else {/* file was packed */
  474.       if (!pk_out) pk_out = malloc(pksize);
  475.  
  476.       if (hblock->m.srcsum[1] != 'x') {/* Old decompression */
  477.          if (!pk_out || lzgetmem()) {
  478.             (void)fprintf(myout, "%s\n", no_mem);
  479.             done(ESMALL);
  480.          }
  481.          thisread = 0; indput = 0; thiscsum = 0;
  482.  
  483.          l = lzdecode(arcget, dstput, codesize);
  484.          (void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
  485.          if (indput > 0 && write(o_file, pk_out, indput) != indput)
  486.             extwrerr();
  487.          if (l != codesize) {
  488.             (void)fprintf(myout, "Tar: \'%s\' decode error\n", ofname);
  489.             if (!i_flag) done(EINTER);
  490.          }
  491.          if (thiscsum != longcsum) {
  492.             (void)fprintf(myout, "Tar: \'%s\' checksum error\n", ofname);
  493.          }
  494.       } else {/* Inflation */
  495.          if (!pk_out || unzalloc()) {
  496.             (void)fprintf(myout, "%s\n", no_mem);
  497.             done(ESMALL);
  498.          }
  499.          thisread = 0; indput = 0; thiscsum = 0;
  500.          if (unzopen(arcget, ZIP_RAW)) {
  501.             (void)fprintf(myout, "Tar: unzip error: %s\n",
  502.                                  ziperrlist[ziperror]);
  503.             done(EINTER);
  504.          }
  505.          do {
  506.             j = unzread(pk_out, pksize);
  507.             if (j > 0) {
  508.                if (write(o_file, pk_out, j) != j) {
  509.                   if (v_flag) (void)fprintf(myout, "\n");
  510.                   extwrerr();
  511.                }
  512.                if (v_flag) percent(thisread, st.st_size);
  513.             }
  514.          } while (j == pksize);
  515.          (void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
  516.  
  517.          if (j != -1) {
  518.             if ((j = unzclose()) == 0) {
  519.                if (getcrc() != longcsum) j = ziperror = BADCRC;
  520.             }
  521.          }
  522.          if (j) {
  523.             (void)fprintf(myout,"Unzip %s: %s\n",
  524.                (j == -1 ? "error" : "warning"), ziperrlist[ziperror]);
  525.             if (j == -1) done(EINTER);
  526.          }
  527.       }
  528.    }
  529. xend:
  530.    j = nx > 0 && nx < allx;
  531. #ifdef MSDOS
  532.    if (!j) setime(o_file, st.st_mtime);
  533. #endif
  534.    (void)close(o_file);
  535.    return j;
  536. fault:
  537.    if (o_file >= 0) (void)close(o_file);
  538.    skipfile();
  539.    return ERROR;
  540. }
  541.  
  542. void makelink(fname, lname)
  543. char *fname, *lname;
  544. {
  545. #ifdef MSDOS
  546. #  define BUFSIZE 8192
  547.    char *buffer = NULL;
  548.    int bufsize = BUFSIZE;
  549. #endif
  550.    register j;
  551.  
  552. #ifdef UNIX
  553.    (void)unlink(fname);
  554.    if ((j = link(lname, fname)) < 0) {
  555.       if (testdir(fname) == TRUE) j = link(lname, fname);
  556.    }
  557.    if (j < 0)
  558.       (void)fprintf(myout,
  559.          "Tar: can\'t link \'%s\' to \'%s\'\n", fname, lname);
  560.    else
  561. #endif
  562. #ifdef MSDOS
  563.    if (l_flag) {/* copy file */
  564.       int inp, out;
  565.       char *buffer; int bufsize;
  566.       long rsize, mtime;
  567.  
  568.       if ((buffer = malloc(BUFSIZE)) == NULL) {
  569.          if (pk_out) {
  570.             buffer = pk_out;
  571.             bufsize = pksize;
  572.          } else {
  573.             buffer = (char *)hblock;
  574.             bufsize = BLKSIZE;
  575.          }
  576.       }
  577.       if ((inp = open(lname, O_RDONLY+O_BINARY)) < 0) {
  578.          cantopen(lname); goto quit;
  579.       }
  580.       if ((out = newfile(fname, st.st_mode)) < 0) {
  581.          (void)close(inp); goto quit;
  582.       }
  583.       rsize = st.st_size;
  584.       mtime = st.st_mtime;
  585.       do {
  586.          if ((j = read(inp, buffer, bufsize)) > 0) {
  587.             rsize -= j;
  588.             if (write(out, buffer, j) != j) {
  589.                extwrerr(); j = ERROR;
  590.             }
  591.          }
  592.       } while (j == bufsize);
  593.       if (j >= 0) setime(out, mtime);
  594.       (void)close(out);
  595.       (void)close(inp);
  596.       if (j < 0) goto quit;
  597.       if (v_flag) (void)fprintf(myout, "x %s copied from %s\n", fname, lname);
  598.       if (rsize != 0)
  599.          (void)fprintf(myout,
  600.             "Tar: warning \'%s\' real size differs from the recorded\n",fname);
  601.    } else
  602. #endif
  603.    if (v_flag) (void)fprintf(myout, "x %s linked to %s\n", fname, lname);
  604. #ifdef MSDOS
  605. quit:
  606.    if (buffer != NULL && bufsize == BUFSIZE) free(buffer);
  607. #endif
  608. }
  609.